﻿using Dapper;
using System.Collections.Generic;
using System.Data;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace Gaea
{
    /// <summary>
    /// Gaea数据库驱动基类
    /// 实现MySQL Oracle SQLServer数据库的相同部分的功能，数据增删改查以及相同的T-SQL组装
    /// </summary>
    public abstract class GaeaAdapter : IGaeaAdapter
    {
        /// <summary>
        /// T-SQL语句中列名与参数的格式 例如columnName=@例如columnName
        /// </summary>
        /// <param name="columnName"></param>
        /// <returns></returns>
        public abstract string AppendColumnNameEqualsValue(string columnName);

        /// <summary>
        /// T-SQL语句Delete All操作的组装
        /// </summary>
        /// <param name="name">GaeaName</param>
        /// <param name="keyRestart">是否重启种子列</param>
        /// <returns></returns>
        public virtual string DeleteAllCommandText(string name, bool keyRestart)
        {
            return $"DELETE FROM {name}";
        }

        /// <summary>
        /// T-SQL语句Delete操作的组装
        /// </summary>
        /// <param name="name">GaeaName</param>
        /// <param name="keyProperties">实例详细字段信息</param>
        /// <returns></returns>
        public virtual string DeleteCommandText(string name, List<PropertyInfo> keyProperties)
        {
            var stringBuilder = new StringBuilder();
            stringBuilder.AppendFormat("DELETE FROM {0} WHERE ", name);
            for (var i = 0; i < keyProperties.Count; i++)
            {
                var property = keyProperties[i];
                stringBuilder.Append(AppendColumnNameEqualsValue(property.Name));
                if (i < keyProperties.Count - 1)
                    stringBuilder.Append(" AND ");
            }
            return stringBuilder.ToString();
        }

        /// <summary>
        /// T-SQL语句 依据编号Id获得实体操作的组装
        /// </summary>
        /// <param name="paramName">参数名</param>
        /// <param name="name">GaeaName</param>
        /// <param name="key">key</param>
        /// <returns></returns>
        public virtual string FindByIdCommandText(out string paramName, string name, string key)
        {
            paramName = "@id";
            return $"SELECT * FROM {name} WHERE {key}={paramName}";
        }

        /// <summary>
        /// T-SQL语句Find All操作的组装
        /// </summary>
        /// <param name="name">GaeaName</param>
        /// <returns></returns>
        public virtual string FindAllCommandText(string name)
        {
            return "SELECT * FROM " + name;
        }

        /// <summary>
        /// 数据插入操作的实现
        /// </summary>
        /// <param name="connection">Db Connection</param>
        /// <param name="transaction">Db Transaction</param>
        /// <param name="commandText">T-SQL</param>
        /// <param name="entityToInsert">实例</param>
        /// <param name="commandTimeout">超时时间</param>
        /// <returns>影响行数</returns>
        public virtual int Insert(IDbConnection connection, IDbTransaction transaction, string commandText, object entityToInsert, int? commandTimeout)
        {
            return connection.ExecuteScalar<int>(commandText, entityToInsert, transaction, commandTimeout);
        }

        /// <summary>
        ///  数据插入操作的实现 异步
        /// </summary>
        /// <param name="connection">Db Connection</param>
        /// <param name="transaction">Db Transaction</param>
        /// <param name="commandText">T-SQL</param>
        /// <param name="entityToInsert">实例</param>
        /// <param name="commandTimeout">超时时间</param>
        /// <returns>影响行数</returns>
        public virtual Task<int> InsertAsync(IDbConnection connection, IDbTransaction transaction, string commandText, object entityToInsert, int? commandTimeout)
        {
            return connection.ExecuteScalarAsync<int>(commandText, entityToInsert, transaction, commandTimeout);
        }

        /// <summary>
        /// T-SQL语句 插入操作的组装
        /// </summary>
        /// <param name="name">GaeaName</param>
        /// <param name="columnProperties">实例详细字段信息</param>
        /// <returns></returns>
        public abstract string InsertCommandText(string name, List<PropertyInfo> columnProperties);

        /// <summary>
        ///  T-SQL语句 更新操作的组装
        /// </summary>
        /// <param name="name"></param>
        /// <param name="columnProperties"></param>
        /// <param name="keyProperties"></param>
        /// <returns></returns>
        public virtual string UpdateCommandText(string name, List<PropertyInfo> columnProperties, List<PropertyInfo> keyProperties)
        {
            var stringBuilder = new StringBuilder();
            stringBuilder.AppendFormat("UPDATE {0} SET ", name);
            for (var i = 0; i < columnProperties.Count; i++)
            {
                var property = columnProperties[i];
                stringBuilder.Append(AppendColumnNameEqualsValue(property.Name));
                if (i < columnProperties.Count - 1)
                    stringBuilder.Append(", ");
            }
            stringBuilder.Append(" WHERE ");
            for (var i = 0; i < keyProperties.Count; i++)
            {
                var property = keyProperties[i];
                stringBuilder.Append(AppendColumnNameEqualsValue(property.Name));
                if (i < keyProperties.Count - 1)
                    stringBuilder.Append(" AND ");
            }
            return stringBuilder.ToString();
        }
    }
}
